package main

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"time"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/dialog"
	"fyne.io/fyne/v2/widget"

	"hardwareInfo/hardware"
	"hardwareInfo/license"
)

func main() {
	// Create Fyne application
	myApp := app.New()
	myWindow := myApp.NewWindow("Hardware License Generator")
	myWindow.Resize(fyne.NewSize(320, 90))
	myWindow.CenterOnScreen()

	// Create UI components
	dateLabel := widget.NewLabel("Expiry Date:")
	dateEntry := widget.NewEntry()
	dateEntry.SetText(time.Now().AddDate(0, 0, 30).Format("2006-01-02"))
	dateEntry.SetPlaceHolder("YYYY-MM-DD")

	// Create confirm button
	confirmButton := widget.NewButton("Generate License", func() {
		generateLicense(dateEntry.Text, myWindow)
	})

	// Layout
	content := container.NewVBox(
		container.NewGridWithColumns(2, dateLabel, dateEntry),
		widget.NewSeparator(),
		confirmButton,
	)

	myWindow.SetContent(content)
	myWindow.ShowAndRun()
}

// generateLicense Generate License function
func generateLicense(expiryDateStr string, window fyne.Window) {
	// Validate date format
	if expiryDateStr == "" {
		dialog.ShowError(fmt.Errorf("Please enter expiry date"), window)
		return
	}
	
	// Validate date format
	_, err := time.Parse("2006-01-02", expiryDateStr)
	if err != nil {
		dialog.ShowError(fmt.Errorf("Invalid date format, please use YYYY-MM-DD format"), window)
		return
	}

	// Show progress dialog
	progressDialog := dialog.NewCustom("Generating License...", "", container.NewVBox(
		widget.NewProgressBarInfinite(),
		widget.NewLabel("Getting hardware information..."),
	), window)
	progressDialog.Show()

	// Execute generation logic in new goroutine
	go func() {
		defer progressDialog.Hide()
		
		fmt.Println("Detecting hardware information...")

		// Get hardware information
		hwInfo, err := hardware.GetHardwareInfo()
		if err != nil {
			dialog.ShowError(fmt.Errorf("Failed to get hardware information: %v", err), window)
			return
		}

		// Add expiry time and admin field
		hwInfo.ExpiryDate = expiryDateStr
		hwInfo.Admin = false // Fixed to false

		// Output hardware information to console
		fmt.Println("\n=== Hardware Information ===")
		fmt.Printf("CPU ID: %s\n", hwInfo.CPUID)
		fmt.Printf("CPU Name: %s\n", hwInfo.CPUName)
		fmt.Printf("MAC Address: %s\n", hwInfo.MacAddress)
		fmt.Printf("Expiry Date: %s\n", hwInfo.ExpiryDate)
		fmt.Printf("Admin: %t\n", hwInfo.Admin)

		// Serialize hardware information to JSON
		jsonData, err := json.MarshalIndent(hwInfo, "", "  ")
		if err != nil {
			dialog.ShowError(fmt.Errorf("Failed to serialize JSON: %v", err), window)
			return
		}

		// Generate filename (with current timestamp)
		timestamp := time.Now().Format("20060102-150405")
		filename := fmt.Sprintf("hardware-info-%s.json", timestamp)
		
		// Ensure file path exists
		outputDir := "output"
		if err := os.MkdirAll(outputDir, 0755); err != nil {
			dialog.ShowError(fmt.Errorf("Failed to create output directory: %v", err), window)
			return
		}

		filePath := filepath.Join(outputDir, filename)

		// Save JSON file
		err = os.WriteFile(filePath, jsonData, 0644)
		if err != nil {
			dialog.ShowError(fmt.Errorf("Failed to save JSON file: %v", err), window)
			return
		}

		fmt.Printf("\nHardware information saved to file: %s\n", filePath)
		
		// Show JSON content preview
		fmt.Println("\nJSON content preview:")
		fmt.Println(string(jsonData))

		// Generate hardware fingerprint
		hardwareHash := license.GenerateHardwareHash(
			hwInfo.CPUID,
			hwInfo.CPUName,
			hwInfo.MacAddress,
			"", // Don't use public IP
		)

		fmt.Printf("\nHardware fingerprint: %s\n", hardwareHash)

		// Generate License
		fmt.Println("Generating License...")
		licenseObj, err := license.GenerateLicense(hardwareHash, expiryDateStr, false)
		if err != nil {
			dialog.ShowError(fmt.Errorf("Failed to generate License: %v", err), window)
			return
		}

		// Save License as JSON file to root directory
		licenseJSON, err := json.MarshalIndent(licenseObj, "", "  ")
		if err != nil {
			dialog.ShowError(fmt.Errorf("Failed to serialize License: %v", err), window)
			return
		}

		// License file saved in root directory
		licenseFilename := "license.json"
		licenseFilePath := licenseFilename // Save directly to root directory
		err = os.WriteFile(licenseFilePath, licenseJSON, 0644)
		if err != nil {
			dialog.ShowError(fmt.Errorf("Failed to save License file: %v", err), window)
			return
		}

		fmt.Printf("\nLicense generated and saved to: %s\n", licenseFilePath)
		fmt.Printf("License content:\n%s\n", string(licenseJSON))

		// Show success message and close window
		dialog.ShowInformation("Success", 
			fmt.Sprintf("License generated successfully!\n\nHardware info file: %s\nLicense file: %s\n\nWindow will close automatically.", 
				filePath, licenseFilePath), window)
		
		// Close window and exit program after showing success message
		go func() {
			window.Close() // Close the window
			os.Exit(0) // Exit the program
		}()
	}()
}